package com.rojored.module
{

import com.adobe.cairngorm.module.ILoadPolicy;
import com.adobe.cairngorm.module.IViewLoader;
import com.rojored.module.api.LoadModuleErrorMsg;
import com.rojored.module.api.LoadModuleMsg;
import com.rojored.module.api.LoadModuleReadyMsg;
import com.rojored.module.api.ModuleContextReadyMsg;
import flash.events.Event;
import flash.events.IEventDispatcher;
import mx.events.ModuleEvent;

/**
 *  Cairngorm module loader load policy that will wait for an explicit
 *  LoadModuleMsg to initialize the loading of module.
 *
 *  @see http://sourceforge.net/adobe/cairngorm/wiki/HowToUseCairngormModule/#LoadPolicy
 */
public class ExplicitLoadPolicy implements ILoadPolicy
{

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor
     */
    public function ExplicitLoadPolicy()
    {
        super();
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private var loader:IViewLoader;

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //--------------------------------------
    //  dispatcher
    //--------------------------------------

    [MessageDispatcher]

    /**
     *  Parsley message dispatcher.
     */
    public var dispatcher:Function;

    //--------------------------------------------------------------------------
    //
    //  Methods: ILoadPolicy
    //
    //--------------------------------------------------------------------------

    /**
     *  Start applying the load policy for the given loader and module.
     */
    public function start(loader:IViewLoader):void
    {
        this.loader = loader;
        attachListeners(loader as IEventDispatcher);
    }

    /**
     *  Stop applying the load policy for the given loader and module.
     */
    public function stop(loader:IViewLoader):void
    {
        loader = null;
        removeListeners(loader as IEventDispatcher);
    }

    /**
     *  Trigger the load
     */
    public function load(loader:IViewLoader):void
    {
        loader.loadModule();
    }

    /**
     *  Trigger the unload
     */
    public function unload(loader:IViewLoader):void
    {
        loader.unloadModule();
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Attach listeners to the loader events.
     */
    private function attachListeners(loader:IEventDispatcher):void
    {
        if (!loader)
            return;

        loader.addEventListener(ModuleEvent.READY, loader_readyHandler);
        loader.addEventListener("contextReady", loader_contextReadyHandler);
        loader.addEventListener(ModuleEvent.ERROR, loader_errorHandler);
    }

    /**
     *  @private
     */
    private function removeListeners(loader:IEventDispatcher):void
    {
        if (!loader)
            return;

        loader.removeEventListener(ModuleEvent.READY, loader_readyHandler);
        loader.removeEventListener("contextReady",
            loader_contextReadyHandler);
        loader.removeEventListener(ModuleEvent.ERROR, loader_errorHandler);
    }

    //--------------------------------------------------------------------------
    //
    //  Message handlers
    //
    //--------------------------------------------------------------------------

    [MessageHandler]

    /**
     *  @private
     */
    public function loadModuleHandler(msg:LoadModuleMsg):void
    {
        if (!loader)
            return;

        if (loader.moduleId != msg.moduleId)
            return;

        loader.loadModule();
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private function loader_readyHandler(event:ModuleEvent):void
    {
        dispatcher(new LoadModuleReadyMsg(loader.moduleId));
    }

    /**
     *  @private
     */
    private function loader_contextReadyHandler(event:Event):void
    {
        dispatcher(new ModuleContextReadyMsg(loader.moduleId));
    }

    /**
     *  @private
     */
    private function loader_errorHandler(event:ModuleEvent):void
    {
        dispatcher(new LoadModuleErrorMsg(loader.moduleId, event.toString()));
    }
}
}
